import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:cave_flutter/routes/whl_app_pages.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:cave_flutter/utils/whl_toast_utils.dart';
import 'package:cave_flutter/utils/whl_user_utils.dart';
import 'package:dio/dio.dart';
import 'package:get/get.dart' hide FormData, Response;
import 'package:sp_util/sp_util.dart';
import 'dio_log/interceptor/dio_log_interceptor.dart';
import 'whl_network_config.dart';
import 'whl_network_utils.dart';
import 'whl_result_data.dart';
import 'dart:ui' as ui;

final _setCookieReg = RegExp('(?<=)(,)(?=[^;]+?=)');

class WhlHttpManager {
  static Dio? _dio;

  factory WhlHttpManager() => _sharedInstance();
  static WhlHttpManager? _instance;

  WhlHttpManager._() {
    if (null == _dio) {
      _dio = Dio(BaseOptions(connectTimeout: const Duration(milliseconds: 15000)));
      // _dio!.interceptors.add(RequestInterceptors());
      _dio!.interceptors.add(DioLogInterceptor());
      // final cookieJar = CookieJar();
      // _dio!.interceptors.add(CookieManager(cookieJar));
    }
  }

  static WhlHttpManager _sharedInstance() {
    _instance ??= WhlHttpManager._();
    return _instance!;
  }

  static int getNowTempStamp() {
    return int.parse((DateTime.now().millisecondsSinceEpoch / 1000).toStringAsFixed(0));
  }

  static Map<String, dynamic> getRequestHeader() {
    String token = WhlNetWorkUtils.getAccessToken();
    //公共参数
    WhlNetWorkConfig config = WhlNetWorkUtils.config;
    Map<String, dynamic> commonParams = {
      'kst': '1',
      'pkg': config.packageName,
      'sys_lan': ui.window.locale.languageCode,
      'lang': ui.window.locale.languageCode,
      'ver': config.versionName,
      'device-id': config.deviceId,
      'platform': config.platform,
      'model': config.model,
      'Authorization':token
    };
    //eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiIxMTIzMTUifQ.6tbcImg6C2YiHpwu1V-z-Mab9HVszcAlH_iUinFT4rk
    return commonParams;
  }

  ///通用的GET请求
  Future<ResponseData> get(api, {required Map<String, dynamic> params, withLoading = false, hideMsg = false}) async {
    _dio!.options.connectTimeout = const Duration(milliseconds: 30000);
    _dio!.options.contentType = "application/json";

    _dio!.options.headers = getRequestHeader();
    if (withLoading) {
      BotToast.showLoading();
    }
    // _dio!.options.headers['Authorization'] = 'Bearer${WhlNetWorkUtils.getAccessToken()}';
    try {
      Response response = await _dio!.get(api, queryParameters: params);
      return httpSuccessHandle(response, hideMsg, withLoading: withLoading);
    } on DioException catch (e) {
      return httpErrorHandle(e, hideMsg: hideMsg, withLoading: withLoading);
    }
  }

  Future<ResponseData> delete(api, {required Map<String, dynamic> params, withLoading = false, hideMsg = false}) async {
    _dio!.options.connectTimeout = const Duration(milliseconds: 30000);
    _dio!.options.contentType = "application/json";
    _dio!.options.headers['Authorization'] = 'Bearer${WhlNetWorkUtils.getAccessToken()}';
    if (withLoading) {
      BotToast.showLoading();
    }
    try {
      Response response = await _dio!.delete(api, queryParameters: params);
      return httpSuccessHandle(response, hideMsg, withLoading: withLoading);
    } on DioException catch (e) {
      return httpErrorHandle(e, hideMsg: hideMsg, withLoading: withLoading);
    }
  }

  ///通用的POST请求
  Future<ResponseData> post(api, {required params, isJson = true, hideMsg = false, withLoading = false, isNeedCommonParams = true}) async {
    _dio!.options.connectTimeout = const Duration(milliseconds: 30000);
    _dio!.options.sendTimeout = const Duration(milliseconds: 60000);
    _dio!.options.receiveTimeout = const Duration(milliseconds: 30000);
    _dio!.options.contentType = "application/json";
    _dio!.options.responseType = ResponseType.json;
    if (withLoading) {
      BotToast.showLoading();
    }
    //公共参数
    if (isNeedCommonParams) {
      _dio!.options.headers = getRequestHeader();
    }
    // _dio!.options.headers['Authorization'] = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiIxMTIzMDcifQ.U23cKb3mXN-_MeWFuKLIz8awxsNIbKqtX0QB8MA2l8s';//'Bearer${WhlNetWorkUtils.getAccessToken()}';
    // }
    try {
      Response<dynamic> response = await _dio!.post(api, data: isJson ? params : FormData.fromMap(params));
      return httpSuccessHandle(response, hideMsg, withLoading: withLoading);
    } on DioException catch (e) {
      return httpErrorHandle(e, hideMsg: hideMsg, withLoading: withLoading);
    }
  }

  ///下载文件到本地
  ///urlPath 文件Url
  ///savePath 本地保存位置
  ///downloadProgressCallBack 下载文件回调
  Future<Response> downloadFile(String urlPath, String savePath, {DownloadProgressCallBack? downloadProgressCallBack}) async {
    Dio dio = Dio();
    return await dio.download(urlPath, savePath, onReceiveProgress: downloadProgressCallBack);
  }
}

typedef DownloadProgressCallBack = Function(int count, int total);

///成功处理
Future<ResponseData> httpSuccessHandle(Response response, bool hideMsg,{withLoading = false,}) async {
  if (withLoading == true) {
    BotToast.closeAllLoading();
  }
  ResponseData responseData;
  if (response.data is String || response.data is Map) {
    String responseStr = "";

    if (response.data is Map) {
      responseStr = jsonEncode(response.data);
    } else {
      responseStr = response.data.toString();
    }
    Map<String, dynamic> mapResult = jsonDecode(responseStr);
    responseData = ResponseData.fromJson(mapResult);
  } else {
    responseData = ResponseData.fromJson(response.data);
  }
  if (!responseData.isSuccess()) {
    String errorMsg = responseData.msg ?? "";
    if (errorMsg.isNotEmpty && !hideMsg) {
      BotToast.showText(text: errorMsg);
    }
    if (responseData.code == '10010303'||responseData.code == '401') {
      MyToast.show("登录失效，请重新登录");
      WhlNetWorkUtils.setAccessToken('');
      WhlUserUtils.loginOut();
    }
  }
  return responseData;
}

///处理错误
Future<ResponseData> httpErrorHandle(DioException e, {hideMsg = false,withLoading = false}) async {
  if (withLoading == true) {
    BotToast.closeAllLoading();
  }
  String errorMsg = "";
  if (e.type == DioExceptionType.connectionTimeout || e.type == DioExceptionType.receiveTimeout) {
    errorMsg = WhlNetWorkUtils.config?.requestTimeoutTip ?? '';
  } else {
    errorMsg = WhlNetWorkUtils.config?.requestErrorTip ?? '';
  }
  if (!hideMsg && errorMsg.isNotEmpty) {
    BotToast.showText(text: errorMsg);
  }
  return ResponseData(code: "-1", data: {}, msg: errorMsg);
}

String getCookies(List<Cookie> cookies) {
// Sort cookies by path (longer path first).
  cookies.sort((a, b) {
    if (a.path == null && b.path == null) {
      return 0;
    } else if (a.path == null) {
      return -1;
    } else if (b.path == null) {
      return 1;
    } else {
      return (b.path!.length).compareTo(a.path!.length);
    }
  });
  return cookies.map((cookie) => '${cookie.name}=${cookie.value}').join('; ');
}
